package com.xuecheng.manage_cms.service.impl;

import com.mongodb.client.gridfs.GridFSBucket;
import com.mongodb.client.gridfs.GridFSDownloadStream;
import com.mongodb.client.gridfs.model.GridFSFile;
import com.xuecheng.framework.domain.cms.CmsTemplate;
import com.xuecheng.framework.domain.cms.ext.CmsTemplateExt1;
import com.xuecheng.framework.domain.system.FSFile;
import com.xuecheng.framework.exception.ExceptionCast;
import com.xuecheng.framework.model.response.CommonCode;
import com.xuecheng.framework.model.response.QueryResponseResult;
import com.xuecheng.framework.model.response.QueryResult;
import com.xuecheng.framework.model.response.ResponseResult;
import com.xuecheng.framework.utils.VerifyFileType;
import com.xuecheng.manage_cms.dao.CmsTemplateRepository;
import com.xuecheng.manage_cms.dao.FsFilesRepository;
import com.xuecheng.manage_cms.service.CmsTemplateService;
import org.apache.commons.lang.StringUtils;
import org.bson.types.ObjectId;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.gridfs.GridFsResource;
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

@Service
public class CmsTemplateServiceImpl implements CmsTemplateService {
    @Resource
    private CmsTemplateRepository cmsTemplateRepository;
    @Resource
    private FsFilesRepository fsFilesRepository;
    @Resource
    GridFsTemplate gridFsTemplate;
    @Resource
    GridFSBucket gridFSBucket;

    /**
     * 查询所有的Cms模板信息
     *
     * @return 查询出的结果封装成统一返回对象
     */
    @Override
    public QueryResponseResult findAllTemplate() {
        List<CmsTemplate> all = cmsTemplateRepository.findAll();

        QueryResult<CmsTemplate> queryResult = new QueryResult<>();
        queryResult.setList(all);
        queryResult.setTotal(all.size());
        return new QueryResponseResult(CommonCode.SUCCESS, queryResult);
    }

    /**
     * 根据id查询一个CmsTemplate
     *
     * @param templateId templateId
     * @return 结果
     */
    public CmsTemplate findById(String templateId) {
        if (StringUtils.isEmpty(templateId)) {
            return null;
        }
        Optional<CmsTemplate> optional = cmsTemplateRepository.findById(templateId);
        return optional.orElse(null);
    }

    /**
     * @param page 第几页
     * @param size 每页显示多少
     *             分页查询所有的Cms模板信息
     * @return 查询出的结果封装成统一返回对象
     */
    @Override
    public QueryResponseResult findListByPagination(int page, int size) {
        Pageable pageable = PageRequest.of(page - 1, size);
        Page<CmsTemplate> all = cmsTemplateRepository.findAll(pageable);
        QueryResult<CmsTemplateExt1> queryResult = new QueryResult<>();
        List<CmsTemplateExt1> list = new ArrayList<>();
        for (CmsTemplate cmsTemplate : all) {
            // 存入模板信息
            CmsTemplateExt1 cmsTemplateExt1 = new CmsTemplateExt1();
            cmsTemplateExt1.setCmsTemplate(cmsTemplate);
            // 根据模板文件id查询模板信息 fs.files表
            String templateFileId = cmsTemplate.getTemplateFileId();
            Optional<FSFile> optional = fsFilesRepository.findById(templateFileId);
            if (optional.isPresent()) {
                cmsTemplateExt1.setFsFile(optional.get());
            } else {
                cmsTemplateExt1.setFsFile(null);
            }
            list.add(cmsTemplateExt1);
        }
        queryResult.setList(list);
        queryResult.setTotal(all.getTotalElements());
        return new QueryResponseResult(CommonCode.SUCCESS, queryResult);
    }

    /**
     * 上传模板文件
     *
     * @param file              模板文件
     * @param templateName      模板文件名
     * @param templateParameter 模板参数
     * @param siteId            站点id
     * @return 响应结果
     */
    @Override
    public ResponseResult uploadTemplate(MultipartFile file, String templateName, String templateParameter, String siteId) {
        if (StringUtils.isEmpty(templateName)) {
            ExceptionCast.cast(CommonCode.INVALID_JSON_PARAMETER);
        }
        if (StringUtils.isEmpty(siteId)) {
            ExceptionCast.cast(CommonCode.INVALID_JSON_PARAMETER);
        }
        // 得到文件名
        String originalFilename = file.getOriginalFilename();
        String fileType = null;
        try {
            fileType = VerifyFileType.getFileTypeByHEX(file.getInputStream());
        } catch (IOException e) {
            ExceptionCast.cast(CommonCode.SERVER_ERROR);
        }
        if (fileType == null) {
            fileType = originalFilename;
        }
        if (!"html".equals(fileType)) {
            ExceptionCast.cast(CommonCode.INVALID_JSON_PARAMETER);
        }
        try {
            CmsTemplate cmsTemplate = new CmsTemplate();
            cmsTemplate.setSiteId(siteId);
            cmsTemplate.setTemplateParameter(templateParameter);
            cmsTemplate.setTemplateName(templateName);
            ObjectId objectId = gridFsTemplate.store(file.getInputStream(), originalFilename);
            cmsTemplate.setTemplateFileId(objectId.toString());
            cmsTemplateRepository.save(cmsTemplate);
        } catch (IOException e) {
            ExceptionCast.cast(CommonCode.SERVER_ERROR);
        }
        return new ResponseResult(CommonCode.SUCCESS);
    }

    /**
     * 根据模板id删除模板
     *
     * @param templateId 模板id
     * @return 操作响应
     */
    @Override
    public ResponseResult deleteTemplate(String templateId) {
        if (StringUtils.isEmpty(templateId)) {
            return new ResponseResult(CommonCode.INVALID_JSON_PARAMETER);
        }
        Optional<CmsTemplate> optional = cmsTemplateRepository.findById(templateId);
        if (optional.isPresent()) {
            CmsTemplate cmsTemplate = optional.get();
            String templateFileId = cmsTemplate.getTemplateFileId();
            // 删除template表
            cmsTemplateRepository.deleteById(templateId);
            gridFsTemplate.delete(Query.query(Criteria.where("_id").is(templateFileId)));
            return new ResponseResult(CommonCode.SUCCESS);
        } else {
            return new ResponseResult(CommonCode.INVALID_JSON_PARAMETER);
        }
    }

    /**
     * 根据模板id导出模板
     *
     * @param cmsTemplate 模板
     * @return Map<String, Object> 文件名和流
     */
    @Override
    public Map<String, Object> downTemplate(CmsTemplate cmsTemplate) {
        String templateFileId = cmsTemplate.getTemplateFileId();
        //根据id查询文件
        GridFSFile gridFSFile = gridFsTemplate.findOne(Query.query(Criteria.where("_id").is(templateFileId)));
        if (gridFSFile == null) {
            return null;
        } else {
            Map<String, Object> map = new HashMap<>();
            //打开流下载对象
            GridFSDownloadStream downloadStream = gridFSBucket.openDownloadStream(gridFSFile.getObjectId());
            map.put("fileName", gridFSFile.getFilename());
            //获取流对象
            GridFsResource gridFsResource = new GridFsResource(gridFSFile, downloadStream);
            try {
                map.put("inputStream", gridFsResource.getInputStream());
                return map;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 上传模板文件
     *
     * @param multipartFile     模板文件
     * @param templateId        模板id
     * @param templateName      模板文件名
     * @param templateParameter 模板参数
     * @param siteId            站点id
     * @return 响应结果
     */
    @Override
    public ResponseResult updateTemplate(MultipartFile multipartFile, String templateId, String templateName, String templateParameter, String siteId) {
        if (multipartFile == null ) {
            ExceptionCast.cast(CommonCode.INVALID_JSON_PARAMETER);
        }
        if (StringUtils.isEmpty(templateId)
                || StringUtils.isEmpty(templateName)
                || StringUtils.isEmpty(siteId)) {
            ExceptionCast.cast(CommonCode.INVALID_JSON_PARAMETER);
        }
        CmsTemplate cmsTemplate = this.findById(templateId);
        if (cmsTemplate ==null){
            ExceptionCast.cast(CommonCode.INVALID_JSON_PARAMETER);
        }
        cmsTemplate.setTemplateName(templateName);
        cmsTemplate.setSiteId(siteId);
        String fileType = null;
        String originalFilename = multipartFile.getOriginalFilename();
        try {
            fileType = VerifyFileType.getFileTypeByHEX(multipartFile.getInputStream());
        } catch (IOException e) {
            ExceptionCast.cast(CommonCode.SERVER_ERROR);
        }
        if (fileType == null) {
            fileType = originalFilename;
        }
        if (!"html".equals(fileType)) {
            ExceptionCast.cast(CommonCode.INVALID_JSON_PARAMETER);
        }
        try {
            gridFsTemplate.delete(Query.query(Criteria.where("_id").is(cmsTemplate.getTemplateFileId())));
            ObjectId objectId = gridFsTemplate.store(multipartFile.getInputStream(), originalFilename);
            cmsTemplate.setTemplateFileId(objectId.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
        cmsTemplateRepository.save(cmsTemplate);
        return new ResponseResult(CommonCode.SUCCESS);
    }
}
